use std::{
    collections::BTreeMap,
    ops::{Deref, DerefMut},
};

use bytes::{Buf, BytesMut};

use crate::{bulk_string::BulkString, RespDecode, RespEncode, RespError, RespFrame, SimpleString};

use super::{calc_total_length, parse_length, BUF_CAP, CRLF_LEN};

// - map: "%<number-of-entries>\r\n<key-1><value-1>...<key-n><value-n>"
impl RespDecode for RespMap {
    const PREFIX: &'static str = "%";
    fn decode(buf: &mut BytesMut) -> Result<Self, RespError> {
        let (end, len) = parse_length(buf, Self::PREFIX)?;
        let total_len = calc_total_length(buf, end, len, Self::PREFIX)?;

        if buf.len() < total_len {
            return Err(RespError::NotComplete);
        }

        buf.advance(end + CRLF_LEN);

        let mut frames = RespMap::new();
        for _ in 0..len {
            let key = SimpleString::decode(buf)?;
            let value = RespFrame::decode(buf)?;
            frames.insert(key.0, value);
        }

        Ok(frames)
    }

    fn expect_length(buf: &[u8]) -> Result<usize, RespError> {
        let (end, len) = parse_length(buf, Self::PREFIX)?;
        calc_total_length(buf, end, len, Self::PREFIX)
    }
}

// map: "%<number-of-entries>\r\n<key-1><value-1>...<key-n><value-n>"
// 先为map的类型实现 encode 方法
impl RespEncode for RespMap {
    fn encode(self) -> Vec<u8> {
        let mut buf = Vec::with_capacity(BUF_CAP);
        let len: usize = self.0.len();
        let first_value = format!("%{}\r\n", len);
        buf.extend_from_slice(&first_value.into_bytes());
        for (key, value) in self.0 {
            buf.extend_from_slice(&SimpleString::new(key).encode());
            buf.extend_from_slice(&value.encode());
        }
        buf
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct RespMap(pub(crate) BTreeMap<String, RespFrame>);

impl Deref for RespMap {
    type Target = BTreeMap<String, RespFrame>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
/// 为map 类型的数据结构实现可变解引用特质
impl DerefMut for RespMap {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
impl RespMap {
    pub fn new() -> Self {
        Self::default()
    }
}

/// 为 map 方法实现默认值
impl Default for RespMap {
    fn default() -> Self {
        Self(BTreeMap::new())
    }
}

// 字符串切面直接转换成RespFrame
impl From<&str> for RespFrame {
    fn from(value: &str) -> Self {
        SimpleString::new(value).into()
    }
}
// u8数组引用直接转换成RespFrame
impl From<&[u8]> for RespFrame {
    fn from(value: &[u8]) -> Self {
        BulkString::new(value).into()
    }
}
//  固定长度的 u8数组引用直接转换成 RespFrame
impl<const N: usize> From<&[u8; N]> for RespFrame {
    fn from(value: &[u8; N]) -> Self {
        BulkString::new(value).into()
    }
}

#[cfg(test)]
mod tests {
    use crate::bulk_string::BulkString;

    use super::*;
    use anyhow::Result;
    use bytes::BytesMut;

    #[test]
    fn test_map_decode() -> Result<()> {
        let mut buf = BytesMut::new();
        buf.extend_from_slice(b"%2\r\n+hello\r\n$5\r\nworld\r\n+foo\r\n$3\r\nbar\r\n");

        let frame = RespMap::decode(&mut buf)?;
        let mut map = RespMap::new();
        map.insert(
            "hello".to_string(),
            BulkString::new(b"world".to_vec()).into(),
        );
        map.insert("foo".to_string(), BulkString::new(b"bar".to_vec()).into());
        assert_eq!(frame, map);
        Ok(())
    }

    //  "%<number-of-entries>\r\n<key-1><value-1>...<key-n><value-n>"
    #[test]
    fn test_map_encode() {
        let mut map = RespMap::default();
        map.insert("hello".to_string(), SimpleString::new("world").into());
        let buf = map.encode();
        // println!("{}", String::from_utf8_lossy(&buf));
        assert_eq!(buf, b"%1\r\n+hello\r\n+world\r\n");
    }
}
